#pragma once

#include <stddef.h>

#include "asio.h"
#include "http.h"
#include "http-response-buffer.h"


class HttpServer;
class HttpRequest;
class HttpResponse;
class HttpDispatcher;


class HttpSession
{
public:
    HttpSession(HttpServer &server);

    virtual ~HttpSession();

protected:
    using UnderRequest = beast::http::request<beast::http::string_body>;
    using UnderRequestBuffer = beast::flat_buffer;
    using UnderResponse = beast::http::response<beast::http::span_body<const char>>;

    virtual void asyncReadHttpRequest(UnderRequestBuffer &requestBuffer, UnderRequest &request, std::function<void(std::error_code ec, size_t readn)> &&cb) = 0;

    virtual void asyncWriteHttpResponse(const UnderResponse &response, std::function<void(std::error_code ec, size_t readn)> &&cb) = 0;

protected:
    void stop();
    void startHandleMessage();

private:
    void removeSelf();
    void afterOneRequestCompleted(std::error_code err);
    void clearPerRequestData();
    void asyncReadRequest();
    void handleHttpRequest(const HttpRequest &request, HttpResponse &response);


private:
    HttpServer &server_;
    UnderRequest request_;
    UnderRequestBuffer requestBuffer_;
    UnderResponse response_;
    HttpResponseBufferHolder responseBufferHolder_;
};

